﻿//自定义类型：位段的相关了解： 
//位段的声明和结构体是类似的，但有三个不同：
	//1.位段的成员必须是int,unsigned int,signed int,char等整型变量
	//2.位段的成员名后边有一个冒号和一个数字
	//3.​​同一结构体内允许混合使用这些类型​​。也可以通过嵌套结构体进一步组合不同位宽的类型，使代码更清晰
#include<stdio.h>
//位段示例： 
struct S
{
	int a:2;//冒号后的数字2实际上代表分配给该变量的bit数，2即为分配给a变量2bit 
	int b:3;//3即为3bit，因此，冒号后的数字不能超过该变量类型的大小 
	int c:4;
};
//位段作用：相比结构体，位段可以在一定程度上节省空间 

//int main()
//{
//	struct S s={1,2,3};
//	printf("%d %d %d\n",s.a,s.b,s.c);//可以像结构体般进行操作 
//	return 0;
//}


//位段的内存分配：
//1.由于一个位段中的元素类型都是相同的，所以位段单次分配内存时会按照该类型所占字节来进行分配，若一个该类型字节不够，则继续分配给相同字节
//2.由于C标准没有详细进行规定，因此位段的空间分配会有很多不确定性（如第一次分配的字节没用完，但却不够下一个元素使用，开辟出新空间后，
//  上一次未使用的内存是否会被浪费？），导致其不能跨平台，因此，注重移植性的程序应避免使用位段 
//注：位段的内存分配与大小端存储基本无关
//注：由于位段中的元素不一定从字节两端的bit位开始，所以不能对位段中的元素取地址，但可以通过取出整个位段的地址并进行强转和位移指针来找到某个字节中储存的数据 
//内存分配示例 
struct S1
{
	//该位段整体是int类型，因此，会先分配4字节（即4*8=32bite） 
	int a:2;//32-2=30
	int b:3;//30-3=27
	int c:4;//27-4=23
};//其中并未出现所分配的字节不够的情况，因此该位段占据4字节 

struct S2
{
	//该位段整体也是int类型，因此，会先分配4字节（即4*8=32bite）
	int a:10;//32-10=22
	int b:12;//22-12=10
	int c:14;//10<14->开辟新空间：4字节 
};//综上，S2开辟了4+4=8字节的空间 

int main()
{
	printf("%d\n",sizeof(struct S1));//4 
	printf("%d\n",sizeof(struct S2));//8
	//可以对S2是否浪费了第一次分配的4个字节进行查验：
	struct S2 s={1,2,3};
	printf("%x\n",*((int*)&s+1));//发现16进制时第5个字节开始打印的数据为3，说明浪费了第一次分配的剩余空间 
	return 0;
}
